package com.example.demo2.executor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
@Slf4j
public class SpringExecutor {
    private final int queueCapacity = Integer.MAX_VALUE;
    private final String namePrefix = "async-service-thread";

    @Bean(name = "testExecutor")
    public Executor testExecutor() {
        log.info("start testExecutor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        int core = Runtime.getRuntime().availableProcessors();
        // 配置核心线程数
        //executor.setCorePoolSize(corePoolSize);
        int corePoolSize = 4;
        executor.setCorePoolSize(Math.min(core, corePoolSize));
        // 配置最大线程数
        //executor.setMaxPoolSize(maxPoolSize);
        //队列满时，启用maxPoolSize个线程
        int maxPoolSize = 8;
        executor.setMaxPoolSize(Math.max((core * 2 + 1), maxPoolSize));
        // 配置队列大小
        executor.setQueueCapacity(queueCapacity);
        // 配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(namePrefix);
        //10秒空闲，回收线程
        int keepAlive = 10;
        executor.setKeepAliveSeconds(keepAlive);
        //executor.setAllowCoreThreadTimeOut(true);
        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
        // 忽略策略
        //executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        // Modified By Fangxm 20200115 修改忽略策略，使其一直增加
        executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                if (!executor.isShutdown()) {
                    try {
                        executor.getQueue().put(r);
                    } catch (InterruptedException e) {
                        log.error(e.getMessage(), e);
                    }
                }
            }
        });
        //执行初始化
        executor.initialize();
        return executor;
    }
}
